#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include "LockGuard.hpp"

using namespace std;

#define NUM 4

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

class threadData
{
public:
    threadData(int number /*, pthread_mutex_t *mutex*/)
    {
        threadname = "thread-" + to_string(number);
        // lock = mutex;
    }

public:
    string threadname;
    // pthread_mutex_t *lock;
};

int tickets = 1000; // 用多线程，模拟一轮抢票

// void *getTicket(void *args)
// {
//     threadData *td = static_cast<threadData *>(args);
//     const char *name = td->threadname.c_str();
//     while (true)
//     {
//         //线程对于锁的竞争能力可能会不同
//         // pthread_mutex_lock(td->lock); // 申请锁成功，才能往后执行，不成功，阻塞等待
//         pthread_mutex_lock(&lock);
//         if (tickets > 0)
//         {
//             usleep(1000);
//             printf("who=%s, get a ticket: %d\n", name, tickets);
//             tickets--;
//             // pthread_mutex_unlock(td->lock);
//             pthread_mutex_unlock(&lock);
//         }
//         else
//         {
//             break;
//             // pthread_mutex_unlock(td->lock);
//             pthread_mutex_unlock(&lock);
//         }
//         usleep(13);//抢到票之后，多线程还要执行得到票之后的后续动作，usleep模拟
//     }
//     printf("%s....quit\n", name);

//     return nullptr;
// }

void *getTicket(void *args)
{
    threadData *td = static_cast<threadData *>(args);
    const char *name = td->threadname.c_str();
    while (true)
    {
        {//借用临时对象的生命周期，实现自动上锁解锁
            LockGuard lockgard(&lock); // 临时的LockGuard对象，RAII风格的锁！
            if (tickets > 0)
            {
                usleep(1000);
                printf("who=%s, get a ticket: %d\n", name, tickets);
                tickets--;
            }
            else
            {
                break;
            }
        }//在此过后，临时对象生命周期结束，自动解锁

        usleep(13); // 抢到票之后，多线程还要执行得到票之后的后续动作，usleep模拟
    }
    printf("%s....quit\n", name);

    return nullptr;
}

int main()
{
    // pthread_mutex_t lock;
    // pthread_mutex_init(&lock, nullptr);
    // 创建多线程
    vector<pthread_t> tids;
    vector<threadData *> thread_datas;
    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        threadData *td = new threadData(i /*, &lock*/);
        thread_datas.push_back(td);
        pthread_create(&tid, nullptr, getTicket, thread_datas[i - 1]);
        tids.push_back(tid);
        sleep(1);
    }

    for (int i = 0; i < NUM; i++)
    {
        pthread_join(tids[i], nullptr);
    }

    for (int i = 0; i < NUM; i++)
    {
        delete thread_datas[i];
    }

    // pthread_mutex_destroy(&lock);
    return 0;
}

// #define NUM 3

// // int *p = nullptr;

// __thread int g_val = 100;//线程的局部存储，只存储自定义类型

// struct threadData
// {
//     string threadname;
// };

// string toHex(pthread_t tid)
// {
//     char buffer[128];
//     snprintf(buffer, sizeof(buffer), "0x%x", tid);
//     return buffer;
// }

// // 所有线程都执行这个函数
// void *threadRoutine(void *args)
// {
//     pthread_detach(pthread_self());
//     // int test_i = 0;
//     threadData *td = static_cast<threadData *>(args);
//     // if (td->threadname == "thread-2")
//     //     p = &test_i;
//     string tid = toHex(pthread_self());
//     int pid = getpid();

//     int i = 0;
//     while (i < 3)
//     {
//         cout<<"tid: "<<tid<<", pid: "<<pid<<endl;

//         // cout << "pid: " << getpid() << ", tid: "
//         //      << toHex(pthread_self()) << ", threadname"
//         //      << td->threadname << ", test_i: " << test_i
//         //      << ", &test_t: " << &test_i << endl;

//         // cout << "pid: " << getpid() << ", tid: "
//         //      << toHex(pthread_self()) << ", threadname"
//         //      << td->threadname << ", g_val: " <<  g_val
//         //      << ", & g_val: " << & g_val << endl;
//         i++;
//          g_val++;
//         // test_i++;
//         // sleep(1);
//     }

//     return nullptr;
// }

// void InitThreadData(threadData *td, int number)
// {
//     td->threadname = "thread-" + to_string(number);
// }
// int main()
// {
//     // 创建多线程
//     vector<pthread_t> tids;
//     for (int i = 0; i < NUM; i++)
//     {
//         pthread_t tid;
//         threadData *td = new threadData;
//         InitThreadData(td, i);
//         pthread_create(&tid, nullptr, threadRoutine, td);
//         tids.push_back(tid);
//         sleep(1);
//     }

//     // for(auto i : tids)
//     // {
//     //     pthread_detach(i);//分离线程，直接释放资源
//     // }

//     // sleep(1);
//     // cout << "main thread get a thread local value, val: " << *p << ", &val: " << p << endl;

//     for (int i = 0; i < NUM; i++)
//     {
//         int n = pthread_join(tids[i], nullptr);
//         printf("n = %d, who = 0x%x, why: %s\n",n,tids[i],strerror(n));
//     }

//     return 0;
// }